634762R22">22
+                background: #efefef;
23
+            }
24
+            .video_wrapper, .video_select {
25
+                width: 100%;
26
+                background: #fff;
27
+                margin-bottom: 10px;
28
+                box-sizing: border-box;
29
+            }
30
+            .video_text, .video_select {
31
+                padding: 15px;
32
+            }
33
+            .course_video_name, .video_select_text {
34
+                font-size: 18px;
35
+                font-weight: bold;
36
+                color: #020001;
37
+                padding-bottom: 10px;
38
+            }
39
+            .course_video_desc {
40
+                font-size: 12px;
41
+                color: #999;
42
+            }
43
+            .video_select_item {
44
+                width: 100%;
45
+                text-align: center;
46
+                height: 40px;
47
+                line-height: 40px;
48
+                color: #020001;
49
+                border: 1px solid #e1e1e1;
50
+                border-radius: 5px;
51
+                margin-bottom: 15px;
52
+            }
53
+            .video_selected {
54
+                color: #ce8f8a !important;
55
+                border: 1px solid #ce8f8a;
56
+            }
57
+        </style>
58
+    </head>
59
+    <body>
60
+        <div class="container" >
61
+            <div class="video_wrapper">
62
+                <video id="video" width="100%" height="100%" autoplay controls x-webkit-airplay="true" webkit-playsinline="" playsinline="true" preload="none" poster="" src="{{ video_default.course_video_url }}" data-cursrc="1"></video>
63
+                <div class="video_text">
64
+                    <div class="course_video_name">{{ video_default.course_video_name }}</div>
65
+                    <div class="course_video_desc">{{ video_default.course_video_desc }}</div>
66
+                </div>
67
+            </div>
68
+
69
+            <div class="video_select">
70
+                <div class="video_select_text">选择视频</div>
71
+                {% for video in videos %}
72
+                    <div id="video{{ forloop.counter }}" class="video_select_item {% ifequal forloop.counter 1 %}video_selected{% endifequal %}" data-src="{{ video.course_video_url }}">{{ video.course_video_type }}</div>
73
+                {% endfor %}
74
+            </div>
75
+        </div>
76
+
77
+        <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
78
+        <script src="//cdn.bootcss.com/video.js/6.2.8/video.min.js"></script>
79
+        <script>
80
+            $(function() {
81
+                var video_count = {{ video_count }};
82
+
83
+                $('.video_select_item').click(function () {
84
+                    $this = $(this);
85
+                    $('.video_select_item').removeClass('video_selected');
86
+                    $this.addClass('video_selected');
87
+                    $('#video').attr('src', $this.attr('data-src'));
88
+                })
89
+
90
+                $('#video')[0].onended = function() {
91
+                    var curscr = $(this).attr('data-cursrc');
92
+                    if (curscr >= video_count) {
93
+                        return
94
+                    }
95
+                    var next_video = $('#video' + (parseInt(curscr) + 1));
96
+                    $('#video').attr('src', next_video.attr('data-src'));
97
+                    $('.video_select_item').removeClass('video_selected');
98
+                    next_video.addClass('video_selected');
99
+                };
100
+            });
101
+        </script>
102
+        <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
103
+        <script type="text/javascript" src="{% static 'course/js/jswe-0.0.1.js' %}"></script>
104
+        <script>
105
+            V.initWxData({
106
+                imgUrl: 'http://pai.ai/static/pai2/img/paiai_96_96.png',
107
+                link: 'http://api.pai.ai/wx_oauth2?redirect_url=http://tamron.xfoto.com.cn/page/clerk',
108
+                desc: '店员授权',
109
+                title: '店员授权',
110
+                timeLine: ''
111
+            }, true);
112
+            V.hideOptionMenu();
113
+
114
+            $('#scan').click(function () {
115
+                V.scanQRCode({
116
+                    needResult: 1
117
+                });
118
+            });
119
+            V.wxScanQRCodeSuccess = function (res) {
120
+                $('#code').val(V.parseScanQRCodeResultStr(res.resultStr));
121
+            }
122
+        </script>
123
+    </body>
124
+</html>

+ 77 - 0
page/templates/page/course_list.html

@@ -0,0 +1,77 @@
1
+{% load staticfiles %}
2
+
3
+<!DOCTYPE html>
4
+<html lang="zh-CN">
5
+    <head>
6
+        <meta charset="utf-8">
7
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
8
+        <meta name="format-detection" content="telephone=no,email=no,address=no">
9
+        <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
10
+        <title>课程列表</title>
11
+
12
+        <link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
13
+        <link href="{% static 'page/css/weui.ext.css' %}?v=1" rel="stylesheet" type="text/css" />
14
+
15
+        <style>
16
+            .container {
17
+                position: absolute;
18
+                top: 0;
19
+                right: 0;
20
+                bottom: 0;
21
+                left: 0;
22
+                background: #efefef;
23
+            }
24
+            .course_wrapper {
25
+                text-align: center;
26
+                background: white;
27
+                margin-bottom: 20px;
28
+                padding: 15px 0;
29
+            }
30
+            .course_name {
31
+                font-size: 18px;
32
+                font-weight: bold;
33
+                color: #020001;
34
+            }
35
+            .course_time {
36
+                font-size: 12px;
37
+                color: #999;
38
+            }
39
+            .course_cover>img {
40
+                width: 80%;
41
+                border-radius: 5px;
42
+            }
43
+        </style>
44
+    </head>
45
+    <body>
46
+        <div class="container" >
47
+            {% for course in courses %}
48
+                <div class="course_wrapper" data-courseid="{{ course.course_id }}">
49
+                    <div class="course_name">{{ course.course_name }}</div>
50
+                    <div class="course_time">{{ course.course_time }}分钟</div>
51
+                    <div class="course_cover"><img src="{{ course.course_cover_url }}"></div>
52
+                </div>
53
+            {% endfor %}
54
+        </div>
55
+
56
+        <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
57
+        <script>
58
+            $(function() {
59
+                $('.course_wrapper').click(function () {
60
+                    window.location.href = '{{ domain }}/page/course/info?course_id=' + $(this).attr('data-courseid') + '&{{ params|safe }}';
61
+                })
62
+            });
63
+        </script>
64
+        <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
65
+        <script type="text/javascript" src="{% static 'course/js/jswe-0.0.1.js' %}"></script>
66
+        <script>
67
+            V.initWxData({
68
+                imgUrl: 'http://pai.ai/static/pai2/img/paiai_96_96.png',
69
+                link: 'http://api.pai.ai/wx_oauth2?redirect_url=http://tamron.xfoto.com.cn/page/clerk',
70
+                desc: '店员授权',
71
+                title: '店员授权',
72
+                timeLine: ''
73
+            }, true);
74
+{#            V.hideOptionMenu();#}
75
+        </script>
76
+    </body>
77
+</html>

+ 4 - 0
page/tests.py

@@ -0,0 +1,4 @@
1
+from django.test import TestCase
2
+
3
+
4
+# Create your tests here.

+ 12 - 0
page/urls.py

@@ -0,0 +1,12 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.conf.urls import url
4
+
5
+from page import code_views, info_views, list_views
6
+
7
+
8
+urlpatterns = [
9
+    url(r'^course/code$', code_views.course_code, name='course_code'),
10
+    url(r'^course/list$', list_views.course_list, name='course_list'),
11
+    url(r'^course/info$', info_views.course_info, name='course_info'),
12
+]

+ 4 - 0
page/views.py

@@ -0,0 +1,4 @@
1
+from django.shortcuts import render
2
+
3
+
4
+# Create your views here.

+ 9 - 0
pep8.sh

@@ -0,0 +1,9 @@
1
+#!/bin/bash
2
+
3
+# Ignoring autogenerated files
4
+#  -- Migration directories
5
+# Ignoring error codes
6
+#  -- E128 continuation line under-indented for visual indent
7
+#  -- E501 line too long
8
+
9
+pep8 --exclude=migrations --ignore=E128,E501 .

+ 40 - 0
requirements.txt

@@ -0,0 +1,40 @@
1
+-e git+https://github.com/Brightcells/django-q.git#egg=django-q
2
+CodeConvert==2.0.4
3
+Django==1.11.3
4
+MySQL-python==1.2.5
5
+Pillow==3.4.2
6
+StatusCode==1.0.0
7
+TimeConvert==1.4.1
8
+cryptography==2.0.3
9
+django-curtail-uuid==1.0.0
10
+django-detect==1.0.5
11
+django-file-md5==1.0.1
12
+django-ip==1.0.1
13
+django-json-response==1.1.5
14
+django-logit==1.0.6
15
+django-multidomain==1.1.4
16
+django-paginator2==1.0.3
17
+django-rlog==1.0.7
18
+django-shortuuidfield==0.1.3
19
+django-six==1.0.2
20
+django-uniapi==1.0.0
21
+django-we==1.0.14
22
+djangorestframework==3.6.3
23
+furl==1.0.1
24
+hiredis==0.2.0
25
+isoweek==1.3.3
26
+jsonfield==2.0.2
27
+mock==2.0.0
28
+pep8==1.7.0
29
+pysnippets==1.0.4
30
+pywe-miniapp==1.0.0
31
+pywe-oauth==1.0.5
32
+pywe-response==1.0.1
33
+qiniu==7.1.5
34
+redis==2.10.6
35
+redis-extensions==1.1.1
36
+requests==2.18.4
37
+rlog==0.2
38
+shortuuid==0.5.0
39
+uWSGI==2.0.15
40
+versions==0.10.0

+ 0 - 0
utils/__init__.py


+ 0 - 0
utils/error/__init__.py


+ 51 - 0
utils/error/errno_utils.py

@@ -0,0 +1,51 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from StatusCode import BaseStatusCode, StatusCodeField
4
+
5
+
6
+class ProfileStatusCode(BaseStatusCode):
7
+    """ 用户相关错误码 4000xx """
8
+    PROFILE_NOT_FOUND = StatusCodeField(400001, 'Profile Not Found', description=u'用户不存在')
9
+
10
+
11
+class CourseCodeStatusCode(BaseStatusCode):
12
+    """ 课程兑换码相关错误码 4001xx """
13
+    COURSE_CODE_NOT_FOUND = StatusCodeField(400101, 'Course Code Not Found', description=u'课程兑换码不存在')
14
+    COURSE_CODE_HAS_EXCHANGED = StatusCodeField(400102, 'Course Code Has Exchanged', description=u'课程兑换码已兑换')
15
+
16
+
17
+class CourseStatusCode(BaseStatusCode):
18
+    """ 课程相关错误码 4002xx """
19
+    COURSE_NOT_FOUND = StatusCodeField(400201, 'Course Not Found', description=u'课程不存在')
20
+
21
+
22
+class OrderStatusCode(BaseStatusCode):
23
+    """ 订单/支付相关错误码 4040xx """
24
+    WX_UNIFIED_ORDER_FAIL = StatusCodeField(404000, 'WX Unified Order Fail', description=u'微信统一下单失败')
25
+    WX_ORDER_NOT_FOUND = StatusCodeField(404001, 'WX Order Not Found', description=u'订单不存在')
26
+    WX_ORDER_NOT_PAY = StatusCodeField(404002, 'WX Order Not Pay', description=u'订单未支付')
27
+    WX_ORDER_PAYING = StatusCodeField(404003, 'WX Order Paying', description=u'订单支付中')
28
+    WX_ORDER_PAY_FAIL = StatusCodeField(404009, 'WX Order Pay Fail', description=u'微信支付失败')
29
+    SIGN_CHECK_FAIL = StatusCodeField(404010, 'Sign Check Fail', description=u'签名校验失败')
30
+    FEE_CHECK_FAIL = StatusCodeField(404011, 'FEE Check Fail', description=u'金额校验失败')
31
+    NO_DETAIL_PERMISSION = StatusCodeField(404015, 'No Detail Permission', description=u'无详情权限')
32
+    WX_ORDER_PAID_ALREADY_EXISTS = StatusCodeField(404020, 'WX Order Paid Already Exists', description=u'照片已购买')
33
+
34
+
35
+class PayStatusCode(BaseStatusCode):
36
+    """ 支付相关错误码 4041xx """
37
+
38
+
39
+class WithdrawStatusCode(BaseStatusCode):
40
+    """ 提现相关错误码 4042xx """
41
+    BALANCE_NOT_ENOUGH = StatusCodeField(404200, 'Balance Not Enough', description=u'提现金额不足')
42
+
43
+
44
+class MessageStatusCode(BaseStatusCode):
45
+    """ 消息相关错误码 4090xx """
46
+    MESSAGE_NOT_FOUND = StatusCodeField(409001, 'Message Not Found', description=u'消息不存在')
47
+
48
+
49
+class TokenStatusCode(BaseStatusCode):
50
+    """ 票据相关错误码 4090xx """
51
+    TOKEN_NOT_FOUND = StatusCodeField(409901, 'Token Not Found', description=u'票据不存在')

+ 18 - 0
utils/error/response_utils.py

@@ -0,0 +1,18 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.http import JsonResponse
4
+from StatusCode import StatusCodeField
5
+
6
+
7
+def response_data(status_code=200, message=None, description=None, data={}, **kwargs):
8
+    return dict({
9
+        'status': status_code,
10
+        'message': message,
11
+        'description': description,
12
+        'data': data,
13
+    }, **kwargs)
14
+
15
+
16
+def response(status_code=200, message=None, description=None, data={}, **kwargs):
17
+    message, description = (message or status_code.message, description or status_code.description) if isinstance(status_code, StatusCodeField) else (message, description)
18
+    return JsonResponse(response_data(status_code, message, description, data, **kwargs), safe=False)

+ 0 - 0
utils/redis/__init__.py


+ 6 - 0
utils/redis/connect.py

@@ -0,0 +1,6 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.conf import settings
4
+
5
+
6
+r = settings.REDIS_CACHE

+ 68 - 0
utils/redis/rkeys.py

@@ -0,0 +1,68 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+# 唯一标识相关
4
+UUID_LIST = 'uuid:list'  # List,唯一标识列表
5
+
6
+# 用户相关
7
+PROFILE_INFO = 'profile:info:%s'  # STRING,用户信息,user_id
8
+
9
+# 导游相关
10
+TOUR_GUIDE_GROUP_GEO_INFO = 'tour:guide:group:geo:info:%s'  # ZSET,旅游团地理位置信息,group_id
11
+TOUR_GUIDE_GROUP_GEO_SUBMIT_DT = 'tour:guide:group:geo:submit:dt:%s'  # ZSET,旅游团地理位置最后上传时间,group_id
12
+TOUR_GUIDE_GROUP_CUR_SESSION = 'tour:guide:group:cur:session:%s'  # STRING,旅游团当前Session,group_id,导游设置集合时间的时候更新
13
+TOUR_GUIDE_GROUP_CUR_GATHER_INFO = 'tour:guide:group:cur:gather:info:%s'  # STRING,旅游团当前Session,group_id,导游设置集合时间的时候更新
14
+TOUR_GUIDE_GROUP_USER_GEO_LIST = 'tour:guide:group:user:geo:list:%s:%s:%s'  # LIST,旅游团当前用户地理位置列表,group_id、session_id、user_id
15
+
16
+TOUR_GUIDE_GROUP_USER_OWN = 'tour:guide:group:user:own:%s'  # STRING,导游当前拥有的旅行团,user_id,导游创建旅行团的时候更新
17
+TOUR_GUIDE_GROUP_USER_BELONG = 'tour:guide:group:user:belong:%s'  # STRING,用户当前所属旅行团,user_id,用户加入旅行团的时候更新
18
+
19
+# 群组相关
20
+GROUP_INFO = 'group:info:%s'  # STRING,群组信息,group_id
21
+
22
+# 群组用户相关
23
+GROUP_USERS_INFO = 'group:users:info:%s'  # STRING,群组用户信息,group_id
24
+GROUP_USERS_KV_INFO = 'group:users:kv:info:%s'  # STRING,群组用户信息,group_id
25
+GROUP_USERS_APPLYING_SET = 'group:users:applying:set:%s'  # SET,群组用户申请集合,group_id
26
+GROUP_USERS_PASSED_SET = 'group:users:passed:set:%s'  # SET,群组用户通过集合,group_id
27
+GROUP_USERS_REFUSED_SET = 'group:users:refused:set:%s'  # SET,群组用户拒绝集合,group_id
28
+GROUP_USERS_DELETED_SET = 'group:users:deleted:set:%s'  # SET,群组用户移除集合,group_id
29
+GROUP_USERS_QUIT_SET = 'group:users:quit:set:%s'  # SET,群组用户退出集合,group_id
30
+
31
+# 群组照片相关
32
+GROUP_PHOTO_DATA = 'group:photo:data:%s'  # STRING,群组数据记录,group_id
33
+GROUP_PHOTO_THUMB_UP = 'group:photo:thumb:up:%s:%s'  # STRING,群组照片用户点赞记录,photo_id、user_id
34
+GROUP_PHOTO_COMMENT_LIST = 'group:photo:comment:list:%s'  # STRING,群组照片用户评论列表,photo_id
35
+GROUP_PHOTO_THUMB_UP_LIST = 'group:photo:thumb:up:list:%s'  # STRING,群组照片用户点赞列表,photo_id
36
+GROUP_PHOTO_WATCHER_SET = 'group:photo:watcher:set:%s'  # SET,群组照片用户关注集合,photo_id,关注即评论点赞
37
+GROUP_LAST_PHOTO_PK = 'group:last:photo:pk:%s'  # STRING,群组最后一张照片PK,group_id
38
+
39
+# 摄影师照片相关
40
+LENSMAN_PHOTO_ORDER_RECORD = 'lensman:photo:order:record:%s:%s'  # STRING,摄影师照片购买记录,photo_id、user_id
41
+
42
+# 摄影师简报相关
43
+# 收入
44
+TOTAL_INCOME = 'total:income:%s:%s'  # STRING,总收入,user_id、photo_type
45
+WEEK_INCOME = 'week:income:%s:%s:%s'  # STRING,周收入,user_id、photo_type、Week.thisweek().isoformat()
46
+TODAY_INCOME = 'today:income:%s:%s:%s'  # STRING,日收入,user_id、photo_type、tc.local_string(format='%Y%m%d')
47
+# 上传
48
+TODAY_UPLOAD_PHOTO_AMOUNT = 'today:upload:photo:amount:%s:%s'  # STRING,日上传照片数量,user_id、tc.local_string(format='%Y%m%d')
49
+# 售出
50
+WEEK_SOLD = 'week:sold:%s:%s:%s'  # STRING,周售出,user_id、photo_type、Week.thisweek().isoformat()
51
+
52
+# 摄影师定价相关
53
+LENSMAN_PHOTO_PRICE_FIXED = 'lensman:photo:price:fixed:%s'  # STRING,摄影师照片定价(单位:分),user_id
54
+
55
+# 系统消息相关
56
+SYSTEM_MESSAGE_READ_INFO = 'system:message:read:info:%s'  # STRING,系统消息读取信息,user_id
57
+SYSTEM_MESSAGE_DELETED_INFO = 'system:message:deleted:info:%s'  # STRING,系统消息删除信息,user_id
58
+
59
+# 游客入口相关
60
+GUEST_ENTRANCE_CONTROL_INFO = 'guest:entrance:control:info:%s'  # STRING,游客入口控制信息,src
61
+
62
+# APP 相关
63
+LATEST_APP_INFO = 'latest:app:info:%s'  # STRING,最新 APP 信息,src
64
+APP_SETTINGS_INFO = 'app:settings:info:%s:%s:%s'  # STRING,APP 设置信息,platform、channel、version
65
+APP_PATCH_INFO = 'app:patch:info:%s:%s:%s'  # STRING,APP 补丁信息,platform、version、src
66
+
67
+# BOX 相关
68
+BOX_PROGRAM_VERSION_INFO = 'box:program:version:info'  # STRING,BOX 程序版本信息

+ 7 - 0
utils/url_utils.py

@@ -0,0 +1,7 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.conf import settings
4
+
5
+
6
+def upload_file_url(file_path):
7
+    return file_path and ('{}{}'.format(settings.DOMAIN, file_path.url)) or ''

Change to use django-we support WeChat OAuth2/Share relative api · 37c5365a18 - Gogs: Go Git Service

Change to use django-we support WeChat OAuth2/Share relative api

Brightcells лет %!s(int64=8): %!d(string=назад)
Родитель
Сommit
37c5365a18
10 измененных файлов с 17 добавлено и 81 удалено
  1. 5 5
      api/urls.py
  2. 2 1
      pai2/settings.py
  3. 9 9
      pay/views.py
  4. 1 0
      requirements.txt
  5. 0 0
      wechat/__init__.py
  6. 0 4
      wechat/admin.py
  7. 0 0
      wechat/migrations/__init__.py
  8. 0 4
      wechat/models.py
  9. 0 4
      wechat/tests.py
  10. 0 54
      wechat/views.py

+ 5 - 5
api/urls.py

@@ -1,6 +1,7 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3 3
 from django.conf.urls import url
4
+from django_we import views as we_views
4 5
 
5 6
 from account import views as account_views
6 7
 from account import tourguide_views
@@ -15,7 +16,6 @@ from operation import views as op_views
15 16
 from pay import views as pay_views
16 17
 from photo import views as photo_views
17 18
 from server import server_views
18
-from wechat import views as wechat_views
19 19
 
20 20
 
21 21
 # 帐户相关
@@ -165,14 +165,14 @@ urlpatterns += [
165 165
 
166 166
 # 微信授权相关
167 167
 urlpatterns += [
168
-    url(r'^wx_oauth2$', wechat_views.wx_oauth2, name='wx_oauth2'),
169
-    url(r'^base_redirect$', wechat_views.base_redirect, name='base_redirect'),
170
-    url(r'^userinfo_redirect$', wechat_views.userinfo_redirect, name='userinfo_redirect'),
168
+    url(r'^wx_oauth2$', we_views.we_oauth2, name='we_oauth2'),
169
+    url(r'^base_redirect$', we_views.base_redirect, name='base_redirect'),
170
+    url(r'^userinfo_redirect$', we_views.userinfo_redirect, name='userinfo_redirect'),
171 171
 ]
172 172
 
173 173
 # 微信分享相关
174 174
 urlpatterns += [
175
-    url(r'^wx/jsapi_signature$', wechat_views.wx_jsapi_signature_api, name='wx_jsapi_signature_api'),  # jsapi_signature
175
+    url(r'^wx/jsapi_signature$', we_views.we_jsapi_signature_api, name='we_jsapi_signature_api'),  # jsapi_signature
176 176
 ]
177 177
 
178 178
 # 首页相关

+ 2 - 1
pai2/settings.py

@@ -42,8 +42,9 @@ INSTALLED_APPS = (
42 42
     'django.contrib.messages',
43 43
     'django.contrib.staticfiles',
44 44
     'rest_framework',
45
-    'django_rlog',
46 45
     'django_q',
46
+    'django_rlog',
47
+    'django_we',
47 48
     'api',
48 49
     'account',
49 50
     'box',

+ 9 - 9
pay/views.py

@@ -208,17 +208,17 @@ def wx_order_query_api(request):
208 208
     wxpay = WeChatPay(wxcfg.get('appID'), wxcfg.get('apiKey'), wxcfg.get('mchID'))
209 209
 
210 210
     # 订单查询
211
-    data = wxpay.order.query(transaction_id, order_id)
211
+    query_data = wxpay.order.query(transaction_id, order_id)
212 212
     # 签名校验
213
-    if not check_signature(data, wxcfg.get('apiKey')):
213
+    if not check_signature(query_data, wxcfg.get('apiKey')):
214 214
         return response(OrderStatusCode.SIGN_CHECK_FAIL)
215 215
 
216
-    order.notify_msg = data
217
-    order.transaction_id = data.get('transaction_id', '')
216
+    order.notify_msg = query_data
217
+    order.transaction_id = query_data.get('transaction_id', '')
218 218
     order.save()
219 219
 
220 220
     # 交易状态
221
-    trade_state = data.get('trade_state')
221
+    trade_state = query_data.get('trade_state')
222 222
     # 订单状态判断更新
223 223
     if trade_state == 'SUCCESS':  # 订单支付成功
224 224
         order_paid_success(order)
@@ -272,20 +272,20 @@ def wx_order_detail_api(request):
272 272
 @transaction.atomic
273 273
 def wx_notify_url_api(request):
274 274
     """ 支付异步通知回调地址 """
275
-    data, success = check_pay_notify(request.body, wx_configs=settings.WECHAT)
275
+    notify_data, success = check_pay_notify(request.body, wx_configs=settings.WECHAT)
276 276
     if not success:
277 277
         return HttpResponse(WXPAY_NOTIFY_FAIL)
278 278
 
279 279
     try:
280
-        order = OrderInfo.objects.select_for_update().get(order_id=data.get('out_trade_no', ''), status=True)
280
+        order = OrderInfo.objects.select_for_update().get(order_id=notify_data.get('out_trade_no', ''), status=True)
281 281
     except OrderInfo.DoesNotExist:
282 282
         return HttpResponse(WXPAY_NOTIFY_FAIL)
283 283
 
284 284
     order.notify_msg = request.body
285
-    order.transaction_id = data.get('transaction_id', '')
285
+    order.transaction_id = notify_data.get('transaction_id', '')
286 286
     order.save()
287 287
 
288
-    result_code = data.get('result_code', '')
288
+    result_code = notify_data.get('result_code', '')
289 289
     if result_code == 'SUCCESS':
290 290
         order_paid_success(order)
291 291
     else:

+ 1 - 0
requirements.txt

@@ -18,6 +18,7 @@ django-paginator2==1.0.3
18 18
 django-rlog==1.0.7
19 19
 django-shortuuidfield==0.1.3
20 20
 django-six==1.0.2
21
+django-we==1.0.1
21 22
 djangorestframework==3.6.3
22 23
 furl==1.0.0
23 24
 hiredis==0.2.0

+ 0 - 0
wechat/__init__.py


+ 0 - 4
wechat/admin.py

@@ -1,4 +0,0 @@
1
-from django.contrib import admin
2
-
3
-
4
-# Register your models here.

+ 0 - 0
wechat/migrations/__init__.py


+ 0 - 4
wechat/models.py

@@ -1,4 +0,0 @@
1
-from django.db import models
2
-
3
-
4
-# Create your models here.

+ 0 - 4
wechat/tests.py

@@ -1,4 +0,0 @@
1
-from django.test import TestCase
2
-
3
-
4
-# Create your tests here.

+ 0 - 54
wechat/views.py

@@ -1,54 +0,0 @@
1
-# -*- coding: utf-8 -*-
2
-
3
-from django.conf import settings
4
-from django.shortcuts import redirect
5
-from furl import furl
6
-from json_response import auto_response
7
-from pywe_jssdk import jsapi_signature_params
8
-from pywe_oauth import get_access_info, get_oauth_code_url, get_userinfo
9
-
10
-
11
-JSAPI = settings.WECHAT.get('JSAPI', {})
12
-
13
-
14
-def wx_oauth2(request):
15
-    scope = request.GET.get('scope', 'snsapi_userinfo')
16
-    redirect_url = request.GET.get('redirect_url', '')
17
-    default_url = request.GET.get('default_url', '')
18
-
19
-    if request.weixin:
20
-        redirect_uri = settings.WECHAT_USERINFO_REDIRECT_URI if scope == 'snsapi_userinfo' else settings.WECHAT_BASE_REDIRECT_URI
21
-        return redirect(get_oauth_code_url(JSAPI['appID'], redirect_uri, scope, redirect_url))
22
-
23
-    return redirect(default_url or redirect_url)
24
-
25
-
26
-def base_redirect(request):
27
-    code = request.GET.get('code', '')
28
-    state = request.GET.get('state', '')
29
-
30
-    access_info = get_access_info(JSAPI['appID'], JSAPI['appsecret'], code)
31
-    if 'errcode' in access_info:
32
-        return redirect(settings.WECHAT_OAUTH2_RETRY_REDIRECT_URI.format(state))
33
-
34
-    return redirect(furl(state).add(access_info).url)
35
-
36
-
37
-def userinfo_redirect(request):
38
-    code = request.GET.get('code', '')
39
-    state = request.GET.get('state', '')
40
-
41
-    access_info = get_access_info(JSAPI['appID'], JSAPI['appsecret'], code)
42
-    if 'errcode' in access_info:
43
-        return redirect(settings.WECHAT_OAUTH2_RETRY_REDIRECT_URI.format(state))
44
-
45
-    userinfo = get_userinfo(access_info.get('access_token', ''), access_info.get('openid', ''))
46
-    if 'openid' not in userinfo:
47
-        return redirect(settings.WECHAT_OAUTH2_RETRY_REDIRECT_URI.format(state))
48
-
49
-    return redirect(furl(state).add(userinfo).url)
50
-
51
-
52
-@auto_response
53
-def wx_jsapi_signature_api(request):
54
-    return jsapi_signature_params(JSAPI['appID'], JSAPI['appsecret'], request.GET.get('url', ''))